home *** CD-ROM | disk | FTP | other *** search
/ Programming Languages Suite / ProgramD2.iso / Borland / Borland C++ V5.02 / OWLSRC.PAK / BRUSH.CPP < prev    next >
C/C++ Source or Header  |  1997-05-06  |  9KB  |  345 lines

  1. //----------------------------------------------------------------------------
  2. // ObjectWindows
  3. // Copyright (c) 1992, 1997 by Borland International, All Rights Reserved
  4. //
  5. //$Revision:   10.16  $
  6. //
  7. // Implementation for TBrush GDI Brush object. Includes cache for solid brushes
  8. //----------------------------------------------------------------------------
  9. #pragma hdrignore SECTION
  10. #include <owl/pch.h>
  11. #if !defined(OWL_GDIOBJEC_H)
  12. # include <owl/gdiobjec.h>
  13. #endif
  14.  
  15. OWL_DIAGINFO;
  16. DIAG_DECLARE_GROUP(OwlGDI);        // General GDI diagnostic group
  17.  
  18. #define CACHE_SIZE 8
  19.  
  20. #if !defined(SECTION) || SECTION == 1
  21.  
  22. //
  23. // Internal MRU brush cache to keep most recent solid brushes around cached by
  24. // color
  25. //
  26. class TBrushCache {
  27.   public:
  28.     struct TEntry {
  29.       HANDLE   Handle;
  30.       COLORREF Color;
  31.     };
  32.  
  33.     TBrushCache();
  34.    ~TBrushCache();
  35.  
  36.     static HANDLE Lookup(COLORREF color);
  37.     static void   Float(int i);
  38.     static void   Add(HANDLE handle, COLORREF color);
  39.  
  40.   private:
  41.     static TEntry Entries[CACHE_SIZE];
  42.     static int Size;
  43. };
  44.  
  45. //
  46. // Static data members
  47. //
  48. int TBrushCache::Size = CACHE_SIZE;
  49.  
  50. //
  51. // Initialize all entries to 0.
  52. //
  53. TBrushCache::TEntry TBrushCache::Entries[CACHE_SIZE] = {{0, 0}};
  54.  
  55.  
  56. //
  57. //
  58. //
  59. TBrushCache::TBrushCache()
  60. {
  61. }
  62.  
  63.  
  64. //
  65. //
  66. //
  67. TBrushCache::~TBrushCache()
  68. {
  69.   for (int i = 0; i < Size; i++)
  70.     if (Entries[i].Handle) {
  71.       TGdiObject::RefDec(Entries[i].Handle, false);
  72.       Entries[i].Handle = 0;
  73.     }
  74. }
  75.  
  76. //
  77. // Move an entry to the front, shifting in between ones down
  78. //
  79. void
  80. TBrushCache::Float(int i)
  81. {
  82.   HANDLE handle = Entries[i].Handle;
  83.   COLORREF color = Entries[i].Color;
  84.  
  85.   TRACEX(OwlGDI, 2, "TBrushCache::Float(" << i << ") (" <<
  86.     hex << uint(handle) << ", " << hex << color << ")");
  87.  
  88.   memmove(Entries+1, Entries, sizeof(TEntry)*i);
  89.   Entries[0].Handle = handle;
  90.   Entries[0].Color = color;
  91. }
  92.  
  93. //
  94. // Add a new entry to the front, pushing the last old one off the end.
  95. //
  96. void
  97. TBrushCache::Add(HANDLE handle, COLORREF color)
  98. {
  99.   TRACEX(OwlGDI, 2, "TBrushCache::Add(" << hex << uint(handle) <<
  100.     ", " << hex << color << ")");
  101.   CHECK(Size > 1);
  102.  
  103.   if (Entries[Size-1].Handle)
  104.     TGdiObject::RefDec(Entries[Size-1].Handle, false);  
  105.  
  106.   memmove(Entries+1, Entries, sizeof(TEntry)*(Size-1));
  107.   Entries[0].Handle = handle;
  108.   Entries[0].Color = color;
  109.   TGdiObject::RefAdd(handle, TGdiObject::Brush);
  110. }
  111.  
  112. //
  113. // Lookup a color in the cache, returning the handle if found
  114. //
  115. HANDLE
  116. TBrushCache::Lookup(COLORREF color)
  117. {
  118.   for (int i = 0; i < Size && Entries[i].Handle; i++)
  119.     if (color == Entries[i].Color) {
  120.       TRACEX(OwlGDI, 2, "TBrushCache::Lookup(" << hex << color <<
  121.         "): found " << hex << uint(Entries[i].Handle) << " @" << i);
  122.       Float(i);
  123.       return Entries[0].Handle;  // After Float() our entry is at 0!
  124.     }
  125.   TRACEX(OwlGDI, 2, "TBrushCache::Lookup(" << hex << color << "): not found");
  126.   return 0;
  127. }
  128.  
  129. //
  130. // Static instance of the brush cache used by TBrush
  131. //
  132. static TBrushCache& GetBrushCache() 
  133. {
  134.   static TBrushCache BrushCache;
  135.   return BrushCache;
  136. };
  137.  
  138. //
  139. // Constructors
  140. //
  141.  
  142. //
  143. // Alias an existing brush handle. Assume ownership if autoDelete says so
  144. //
  145. TBrush::TBrush(HBRUSH handle, TAutoDelete autoDelete)
  146. :
  147.   TGdiObject(handle, autoDelete)
  148. {
  149.   if (ShouldDelete)
  150.     RefAdd(Handle, Brush);
  151.   TRACEX(OwlGDI, OWL_CDLEVEL, "TBrush constructed @" << (void*)this <<
  152.                               " with handle " << uint(handle));
  153. }
  154.  
  155. //
  156. // Construct a brush from a solid color. Gets handle from the cache if found,
  157. // otherwise create the brush and add it to the cache
  158. //
  159. TBrush::TBrush(const TColor& color)
  160. {
  161.   ShouldDelete = false;
  162.  
  163. #if 0  
  164.   if (color.IsSysColor())
  165.     Handle = ::GetSysColorBrush(color.Index());
  166.   else
  167. #endif
  168.   {
  169.     COLORREF cr = color;
  170.     if ((Handle = GetBrushCache().Lookup(cr)) != 0)
  171.       return;
  172.     Handle = ::CreateSolidBrush(cr);
  173.   }
  174.   WARNX(OwlGDI, !Handle, 0, "Cannot create solid TBrush " << hex << color);
  175.   CheckValid();
  176.  
  177.   GetBrushCache().Add(Handle, color);
  178.  
  179.   TRACEX(OwlGDI, OWL_CDLEVEL, "TBrush constructed @" << (void*)this <<
  180.                               " with color " << (COLORREF)color);
  181. }
  182.  
  183. //
  184. // Construct a hatch brush of a given color and hatch style
  185. //
  186. TBrush::TBrush(const TColor& color, int style)
  187. {
  188.   Handle = ::CreateHatchBrush(style, color);
  189.   WARNX(OwlGDI, !Handle, 0, "Cannot create hatch TBrush " << hex << color <<
  190.                             " " << style);
  191.   CheckValid();
  192.   RefAdd(Handle, Brush);
  193.   TRACEX(OwlGDI, OWL_CDLEVEL, "TBrush constructed @" << (void*)this <<
  194.                               " with color " << (COLORREF)color <<
  195.                               ", style 0x" << style);
  196. }
  197.  
  198. //
  199. // Construct a pattern brush given a TBitmap
  200. //
  201. TBrush::TBrush(const TBitmap& pattern)
  202. {
  203.   Handle = ::CreatePatternBrush(pattern);
  204.   WARNX(OwlGDI, !Handle, 0, "Cannot create pattern TBrush from bitmap " <<
  205.         hex << (uint)(HBITMAP)pattern);
  206.   CheckValid();
  207.   RefAdd(Handle, Brush);
  208.   TRACEX(OwlGDI, OWL_CDLEVEL, "TBrush constructed @" << (void*)this <<
  209.                               " from bitmap @" << (void*)&pattern);
  210. }
  211.  
  212. //
  213. // Construct a brush from a logical brush definition
  214. //
  215. TBrush::TBrush(const LOGBRUSH far* logBrush)
  216. {
  217.   PRECONDITION(logBrush);
  218.   Handle = ::CreateBrushIndirect((LPLOGBRUSH)logBrush);  // API cast
  219.   WARNX(OwlGDI, !Handle, 0, "Cannot create TBrush from logBrush @" <<
  220.         hex << uint32(LPVOID(logBrush)));
  221.   CheckValid();
  222.   RefAdd(Handle, Brush);
  223.   TRACEX(OwlGDI, OWL_CDLEVEL, "TBrush constructed @" << (void*)this <<
  224.                               " from logBrush @" << (void*)logBrush);
  225. }
  226.  
  227. //
  228. // Construct a copy of an existing brush. Contructed brush will share the
  229. // handle unless NO_GDI_SHARE_HANDLES is defined, in which case a new handle is
  230. // created
  231. //
  232. TBrush::TBrush(const TBrush& src)
  233. {
  234. #if !defined(NO_GDI_SHARE_HANDLES)
  235.   Handle = src.Handle;
  236.   RefAdd(Handle, Brush);
  237. #else
  238.   LOGBRUSH logBrush;
  239.   src.GetObject(logBrush);
  240.   Handle = ::CreateBrushIndirect(&logBrush);
  241.   WARNX(OwlGDI, !Handle, 0, "Cannot create TBrush from TBrush @" <<
  242.         hex << uint32(LPVOID(&src)));
  243.   CheckValid();
  244.   RefAdd(Handle, Brush);
  245. #endif
  246.   TRACEX(OwlGDI, OWL_CDLEVEL, "Copy constructed TBrush @" << (void*)this <<
  247.                               " from TBrush @" << (void*)&src);
  248. }
  249.  
  250. //
  251. // Destroy the C++ object.
  252. //
  253. TBrush::~TBrush()
  254. {
  255.   TRACEX(OwlGDI, OWL_CDLEVEL, "TBrush destructed @" << (void*)this);
  256. }
  257. #endif
  258.  
  259. #if !defined(SECTION) || SECTION == 2
  260.  
  261. //
  262. // Construct a pattern brush given a TDib
  263. //
  264. TBrush::TBrush(const TDib& pattern)
  265. {
  266.   Handle = ::CreateDIBPatternBrush(pattern, pattern.Usage());
  267.   WARNX(OwlGDI, !Handle, 0, "Cannot create pattern TBrush from DIB " <<
  268.         hex << (uint)(HANDLE)pattern);
  269.   CheckValid();
  270.   RefAdd(Handle, Brush);
  271.   TRACEX(OwlGDI, OWL_CDLEVEL, "TBrush constructed @" << (void*)this <<
  272.                               " from DIB @" << (void*)&pattern);
  273. }
  274.  
  275. //----------------------------------------------------------------------------
  276.  
  277. //
  278. // Create a hatch brush.
  279. //
  280. THatch8x8Brush::THatch8x8Brush(const uint8 hatch[], const TColor& fgColor, const TColor& bgColor)
  281. :
  282.   TBrush(Create(hatch, fgColor, bgColor), AutoDelete)
  283. {
  284. }
  285.  
  286. //
  287. // Reconstructs the brush with a new pattern or colors
  288. //
  289. void
  290. THatch8x8Brush::Reconstruct(const uint8 hatch[], const TColor& fgColor, const TColor& bgColor)
  291. {
  292.   if (Handle)
  293.     RefDec(Handle, true);
  294.  
  295.   Handle = Create(hatch, fgColor, bgColor);
  296.   RefAdd(Handle, Brush);
  297. }
  298.  
  299. //
  300. // Private static create member to create or re-create the handle
  301. //
  302. HBRUSH
  303. THatch8x8Brush::Create(const uint8 hatch[], const TColor& fgColor, const TColor& bgColor)
  304. {
  305.   TDib dib(8, 8, 2, DIB_RGB_COLORS);
  306.   uchar HUGE* bits = (uchar HUGE*)dib.GetBits();
  307.   memset(bits, 0, 8*sizeof(uint32));
  308.   for (int i = 0; i < 8; i++)
  309.     bits[(7-i) * sizeof(uint32)] = hatch[i];  // Dib is upside down
  310.   dib.SetColor(0, bgColor);
  311.   dib.SetColor(1, fgColor);
  312.  
  313. #if 0  // Extra step using hbitmap required for some old Win32 versions
  314.   TBitmap bm(dib);
  315.   LOGBRUSH lb = { BS_PATTERN, DIB_RGB_COLORS, (int)HANDLE(bm) };
  316.   HBRUSH handle = ::CreateBrushIndirect(&lb);
  317. #else
  318.   HBRUSH handle = ::CreateDIBPatternBrush(dib, DIB_RGB_COLORS);
  319. #endif
  320.  
  321.   CheckValid(handle);
  322.   return handle;
  323. }
  324.  
  325. //
  326. // Predefined 8x8 hatch patterns
  327. //
  328. const uint8 THatch8x8Brush::Hatch22F1[8] = {
  329.   0x99, 0x33, 0x66, 0xCC, 0x99, 0x33, 0x66, 0xCC
  330. };
  331. const uint8 THatch8x8Brush::Hatch13F1[8] = {
  332.   0x88, 0x11, 0x22, 0x44, 0x88, 0x11, 0x22, 0x44
  333. };
  334. const uint8 THatch8x8Brush::Hatch11F1[8] = {
  335.   0xAA, 0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA, 0x55
  336. };
  337. const uint8 THatch8x8Brush::Hatch22B1[8] = {
  338.   0xCC, 0x66, 0x33, 0x99, 0xCC, 0x66, 0x33, 0x99
  339. };
  340. const uint8 THatch8x8Brush::Hatch13B1[8] = {
  341.   0x44, 0x22, 0x11, 0x88, 0x44, 0x22, 0x11, 0x88
  342. };
  343.  
  344. #endif
  345.